//
// Created by shen on 2024/12/18.
//

#include "FFPlayer.h"

FFPlayer::FFPlayer(JavaCallHelper *_helper,
                   const char *_url,FFStatus *ffStatus):
        helper(_helper),url(_url),ffStatus(ffStatus)
{
    exit= false;
}

void FFPlayer::setVolume(int volume) {


}
void FFPlayer::start() {

    if (!videoDecoder){
        return;
    }
    const char *codecName =  videoDecoder->avCodecContext->codec->name;
    LOGE("codecName %d",codecName);
    int count=0;
    int ret;

    videoDecoder->play();


    while (ffStatus&& !ffStatus->exit) {
        LOGE("onComplete %d",tempIndex);
        //正常播放
        if (!videoDecoder->status->isFramePreview) {

        }
        if (videoDecoder->queue->getQueueSize() > 40) {
            av_usleep(1000*20);
            continue;

        }

        if (videoDecoder->status->isFramePreview) {
            if (videoDecoder->status->isBackSeekFramePreview) {
                av_usleep(1000 * 1);
                continue;
            } else {
                int queueSize = 0;
                queueSize = videoDecoder->frameQueue->getQueueSize();
                if (queueSize >= videoDecoder->cacheFrameNum) {
                    av_usleep(1000 * 10);
                    continue;
                }
            }
        }



        //解码前的数据
        auto *avPacket = av_packet_alloc();
        //从AVFormateContect 读取AVPacket
        ret = av_read_frame(avFormatContext, avPacket);
        if (ret == 0) {
//            if (kzgAudio != NULL && avPacket->stream_index == kzgAudio->streamIndex){
//
//            }else
            if (avPacket->stream_index == videoDecoder->streamIndex) { //视频流
                count++;
                //skip_frame是按帧类型或者说帧的特性，来丢弃一些帧不解码
                LOGE("avpacket pts %lld , %f",avPacket->pts,(avPacket->pts *av_q2d( videoDecoder->time_base)* AV_TIME_BASE));
                if (videoDecoder->avCodecContext->skip_frame != AVDISCARD_DEFAULT
                    && (avPacket->pts * av_q2d(videoDecoder->time_base) * AV_TIME_BASE) >
                       (videoDecoder->seekTime - 1000000)) {
                    videoDecoder->avCodecContext->skip_frame = AVDISCARD_DEFAULT;
                } else if (videoDecoder->status->isBackSeekFramePreview) {
                    videoDecoder->avCodecContext->skip_frame = AVDISCARD_NONREF;
                }
                videoDecoder->queue->putAvPacket(avPacket);
            } else {
                av_packet_free(&avPacket);
                av_free(avPacket);
            }
            LOGE("tempIndex %d",tempIndex);
            tempIndex++;
        } else {
            av_packet_free(&avPacket);
            av_free(avPacket);
            while (ffStatus && ffStatus->exit) {
                if (videoDecoder->queue->getQueueSize() > 0
                    || videoDecoder->frameQueue->getQueueSize() > 0) {
                    av_usleep(1000 * 20);
                    continue;
                } else {
                    if (!ffStatus->seeking) {
                        av_usleep(1000 * 100);
                    }
                    break;
                }//|| videoDecoder->helper->onCallJavaQueueSize(THREAD_CHILD) > 0)
            }
            continue;
        }
    }
    LOGE("onComplete %d",tempIndex);
    if (helper!= nullptr){
        LOGE("onComplete %d",tempIndex);
//      helper->onComplete(THREAD_CHILD);
    }
    exit = true;
}

int FFPlayer::getAVCodecContext(AVCodecParameters *avCodecParameters, AVCodecContext **avCodecContext) {

    int ret;
    //查找解码器
    AVCodec * avCodec = avcodec_find_decoder(avCodecParameters->codec_id);
    //AVCodec，编解码信息
    //AVCodecParameters，编解码参数。  视频信息宽高等
    if (!avCodec){
        exit=true;
        return -1;
    }

    *avCodecContext= avcodec_alloc_context3(avCodec);

    if (!*avCodecContext){
        exit = true;
        return -1;
    }
//    avFormatContext->streams[0]->codecpar->codec_type;
    ret = avcodec_parameters_to_context(*avCodecContext,avCodecParameters);
    if (ret < 0) {
        exit = true;
    }
    //一步解码
    (*avCodecContext)->thread_type = FF_THREAD_FRAME;
    (*avCodecContext)->thread_count = 2;
    ret = avcodec_open2(*avCodecContext,avCodec,0);
    if (ret != 0){

        return -1;
    }

    return 0;
}

void FFPlayer::decodeFFmpegThread() {
    //注册
    avformat_network_init();
    int ret=0;
    //分配文件上下文
    avFormatContext=avformat_alloc_context();

    /**
     * AVInputFormat
     * 输入的格式
     *
     * 传递参数  MP4  相关的参数
    AVDictionary *format_option= nullptr;
    AVDictionaryEntry *t;
    av_dict_set(&format_option,"formatprobesize","10485769",AV_DICT_MATCH_CASE);
    **/
    //打开文件
    ret= avformat_open_input(&avFormatContext,url,0,0);
    if (ret != 0){
        exit = true;
        LOGE("open url fail %d %s" ,ret,url);
        return;
    }
//  avformat_find_stream_info 数据长度
//    avFormatContext->analyzeduration=12;  最大市场
//    avFormatContext->probesize=32;   //最小的字节数  最大是5000000
    AVDictionary  *format_option= nullptr;
    av_dict_set(&format_option,"probesize","32",0);
    /**
     *获取部分文件信息 探测函数
     */
    ret=avformat_find_stream_info(avFormatContext, nullptr);
    if (ret<0){
        exit = true;
        return;
    }


    LOGE("filename - %s",avFormatContext->url);
    LOGE("duration - %lld",avFormatContext->duration);
    LOGE("nb_streams -%u",avFormatContext->nb_streams);
    for (int i = 0; i < avFormatContext->nb_streams; ++i){
        LOGE("stream codec_type -%d",avFormatContext->streams[i]->codecpar->codec_type);
    }
    LOGE("ifomate name - %s",avFormatContext->iformat->name);
    LOGE("iformat long name - %s",avFormatContext->iformat->long_name);

    for (int i = 0; i < avFormatContext->nb_streams; ++i) {
        auto type=avFormatContext->streams[i]->codecpar->codec_type;
        if (type == AVMEDIA_TYPE_AUDIO){

        }else if (type==AVMEDIA_TYPE_VIDEO){
            if (videoDecoder== nullptr){
                videoDecoder=new VideoDecoder(ffStatus,helper);
                videoDecoder->streamIndex=i;   //类型
                videoDecoder->avCodecParameters=avFormatContext->streams[i]->codecpar;//解码器参数
                //该字段与流中的time_base同名，但意思不一样，流中的是与时间相关的时基单位，这里的意思主要是帧率，一般设置为帧率的倒数
                //例如帧率fps={25,1}，那么该字段一般设置为{1,25}，但不一定是帧率的倒数。
                videoDecoder->time_base = avFormatContext->streams[i]->time_base; //时间基数  1/300000  一秒钟被分成这么多
                videoDecoder->duration = avFormatContext->duration; //时间长度
                int num = avFormatContext->streams[i]->avg_frame_rate.num;  //平均帧率
                int den = avFormatContext->streams[i]->avg_frame_rate.den;
                if (num > 0 && den > 0){
                    int fps = num / den;//比如 25 / 1  也就是每秒25帧
                    videoDecoder->defaultDelayTime = 1.0 / fps;
                    videoDecoder->fps = fps;
                }
            }
        }
    }

    if (videoDecoder!= nullptr){
        getAVCodecContext(videoDecoder->avCodecParameters,&videoDecoder->avCodecContext);
        LOGE("视频的帧率:%d,   视频的时长%d  视频宽%d,  视频高%d",videoDecoder->fps,videoDecoder->duration,videoDecoder->avCodecContext->width,videoDecoder->avCodecContext->height);
    }


    /**
     *
     * skip_loop_filter是跳过视频解码的一个环节：in-loop filter
skip_idct是跳过反离散余弦变换，一些老的编码格式有实现

     *
     */
    //环路滤波 不做

    videoDecoder->avCodecContext->skip_loop_filter = AVDISCARD_NONKEY;
    if(ffStatus != NULL && !ffStatus->exit){
        helper->onPrepare(THREAD_CHILD);

    }
//    helper->onLoadMessage(1,THREAD_CHILD);


}
void decode(FFPlayer *FFPlayer){

    FFPlayer->decodeFFmpegThread();
}

void FFPlayer::prepared() {
    if (ffStatus&&!ffStatus->exit) {
        decodeThread = std::thread(decode, this);
    }
}

void FFPlayer::setIsFramePreview(bool isFramePreview) {
    if (videoDecoder){
        if (!isFramePreview&&videoDecoder->showFrameTimestamp>0){

        }
    }
    videoDecoder->setIsFramePreview(isFramePreview);
}
FFPlayer::~FFPlayer() {

}
